import datetime
import pytz

from coin.exchange.base.kr_rest.public_client_base import PublicClientBase
from coin.exchange.okex_v5.kr_rest.native_public_client import OkexNativePublicClient
from coin.exchange.okex.kr_rest.product import OkexProduct
from coin.proto.coin_market_query_pb2 import (
    ProductTicker,
    ExchangeTicker,
    ProductKlineElement,
    ProductKline,
)


class OkexFeedParser(object):
  @staticmethod
  def parse_native_ticker(ticker, product):
    ticker = ticker['data'][0] if 'data' in ticker else ticker
    timestamp = int(ticker['ts']) * 10**6
    return ProductTicker(
        high=float(ticker['high24h']),
        low=float(ticker['low24h']),
        last=float(ticker['last']),
        ask=float(ticker['askPx']),
        ask_size=float(ticker['askSz']),
        bid=float(ticker['bidPx']),
        bid_size=float(ticker['bidSz']),
        volume_24hr=float(ticker['vol24h']),
        exchange_timestamp=timestamp,
        native_symbol=product.native_symbol,
        symbol=product.symbol)

  @staticmethod
  def parse_native_kline(update_msg, product, kline_period):
    klines = update_msg
    kline_group = []
    for kline in klines['data']:
      product_kline = ProductKlineElement(
          kline_timestamp=int(kline[0]) * 10**6,
          open=float(kline[1]),
          high=float(kline[2]),
          low=float(kline[3]),
          close=float(kline[4]),
          volume=float(kline[5]),
          turnover=float(kline[6])
      )
      kline_group.append(product_kline)
    return ProductKline(
        symbol=product.symbol,
        native_symbol=product.native_symbol,
        exchange='Okex',
        market_type='Spot',
        kline_period=str(kline_period),
        klines=kline_group,
    )

  @staticmethod
  def parse_exchange_ticker(exchange_ticker):
    product_ticker_list = []
    for ticker in exchange_ticker['data']:
      product = OkexProduct.FromStrNativeProductNothrow(ticker['instId'])
      if product is None:
        continue
      product_ticker = OkexFeedParser.parse_native_ticker(ticker, product)
      product_ticker_list.append(product_ticker)

    return ExchangeTicker(exchange='Okex', each_ticker=product_ticker_list)


class OkexPublicClient(PublicClientBase):
  ProductType = OkexProduct

  def __init__(self, timeout=10):
    self.npubc = OkexNativePublicClient(timeout=timeout)

  def query_ticker_impl(self, product):
    update = self.npubc.get_ticker(product.symbol)
    update.msg = OkexFeedParser.parse_native_ticker(update.msg, product)
    return update

  def query_exchange_ticker_impl(self):
    update = self.npubc.get_exchange_ticker()
    update.msg = OkexFeedParser.parse_exchange_ticker(update.msg)
    return update

  def query_history_kline_impl(self, product, kline_period, start_time, end_time):
    update = self.npubc.get_history_kline(product.native_symbol, kline_period, start_time, end_time)
    update.msg = OkexFeedParser.parse_native_kline(update.msg, product, kline_period)
    return update

  def query_level_book_impl(self, product):
    raise NotImplementedError()
